home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 April / EnigmA AMIGA RUN 06 (1996)(G.R. Edizioni)(IT)[!][issue 1996-04][Skylink CD V].iso / earcd / utilgfx / raylab.lha / RayLab / source / raylab.c < prev    next >
C/C++ Source or Header  |  1996-02-16  |  18KB  |  539 lines

  1. /*
  2.     name:    raylab.c
  3.  
  4.     Main program
  5.     ------------
  6.  
  7. */
  8.  
  9.  
  10. #include  <stdio.h>
  11. #include  <stdlib.h>
  12. #include  <time.h>
  13.  
  14. #include  "defs.h"
  15. #include  "getworld.h"
  16. #include  "tga.h"
  17.  
  18.  
  19.  
  20. /* Global variables (most mentioned in extern.h) */
  21.  
  22.     long    PicWidth, PicHeight, RecDepth, NumObjects, NumLights;
  23.     CAMERA    Camera;
  24.     COLOR    BackgroundColor;
  25.     long    AntiAliasingRec;
  26.     double    AntiAliasingThreshold, AntiAliasingJitter;
  27.     long    ReqDisplayType, GotDisplayType;
  28.  
  29.     OBJECT    *ObjectArray[maxobjects];
  30.     LIGHT    *LightArray[maxlights];
  31.  
  32.     unsigned char    pixlearray[parraysize];
  33.  
  34.     long    picturerendering;
  35.  
  36.     long    PlaneIntersectionAttempts,PlaneIntersections;
  37.     long    SphereIntersectionAttempts,SphereIntersections;
  38.     long    EllipsoidIntersectionAttempts,EllipsoidIntersections;
  39.     long    TriangleIntersectionAttempts,TriangleIntersections;
  40.     long    BoxIntersectionAttempts,BoxIntersections;
  41.     long    DiscIntersectionAttempts,DiscIntersections;
  42.     long    CylinderIntersectionAttempts,CylinderIntersections;
  43.     long    ShadowAttempts,ShadowHits,ReflectedRays;
  44.  
  45.     FILE    *inputfile,*outputfile;
  46.  
  47.     long    outfileopen,objectalloc,aalinbufalloc,displayopen;
  48.  
  49.  
  50. /* Declaration of entries in the anti-aliasing table(s) */
  51.  
  52. typedef struct AAEntry_Struct AAENTRY;
  53. struct AAEntry_Struct {
  54.     COLOR    Color;
  55.     unsigned char    Done;
  56. };
  57.  
  58.     AAENTRY    aatable[aamaxlevel][aamaxlevel]; /* 9x9 matrix <=> max rec.-level: 4 */
  59.     AAENTRY *aalinebuffer;             /* Line-buffer for major speedup during antialiasing */
  60.  
  61. /**********************************************************************
  62.  *
  63.  *    main()
  64.  *
  65.  **********************************************************************/
  66.  
  67.  
  68. void main(int argc, char *argv[])
  69. {
  70.     time_t    starttrace, endtrace;
  71.     int    spenttime, spent_h, spent_m, spent_s;
  72.  
  73.  
  74.     outfileopen=objectalloc=aalinbufalloc=displayopen=picturerendering=0;
  75.  
  76.     fprintf(stderr,"RayLab v1.0 (c)1995-1996 by Marcus Geelnard\n");
  77.     fprintf(stderr,"-------------------------------------------\n");
  78.  
  79.     if(argc<3) {
  80.         fprintf(stderr,"\n*** Not enough parameters!\n");
  81.         fprintf(stderr,"Usage: %s <input file> <output file>\n",argv[0]);
  82.         exit(0);
  83.     }
  84.  
  85.     if(CreateWorld(argv[1])!=0) {        /* Do some world-declarations */
  86.         exit(1);
  87.     }
  88.     objectalloc=1;
  89.  
  90.     if((outputfile=fopen(argv[2],"wb"))==NULL) {
  91.         fprintf(stderr,"\n*** Could not open output file!\n");
  92.         cleanup();
  93.         exit(1);
  94.     }
  95.     else outfileopen=1;
  96.  
  97.     if(AntiAliasingRec>=1L) {
  98.         if((aalinebuffer=(AAENTRY *)calloc((size_t)(PicWidth*aamaxlevel),sizeof(AAENTRY)))==NULL) {
  99.         fprintf(stderr,"\n*** Could not allocate memory for antialiasing line buffer!\n");
  100.         cleanup();
  101.         exit(1);
  102.         }
  103.         else {
  104.         fprintf(stderr,"(Allocated %ld KB of memory for antialiasing line buffer)\n\n",(long)(PicWidth*aamaxlevel*(long)sizeof(AAENTRY))/(long)1024);
  105.         aalinbufalloc=1;
  106.         }
  107.     }
  108.  
  109.     fprintf(stderr,"Image size:  %ldx%ld\n",PicWidth,PicHeight);
  110.     WriteTgaHeader(outputfile,PicWidth,PicHeight);
  111.  
  112.     fprintf(stderr,"\nLights:     %ld\n",NumLights);
  113.     fprintf(stderr,"Primitives: %ld\n\n",NumObjects);
  114.  
  115.     PlaneIntersectionAttempts = PlaneIntersections = 0;
  116.     SphereIntersectionAttempts = SphereIntersections = 0;
  117.     EllipsoidIntersectionAttempts = EllipsoidIntersections = 0;
  118.     DiscIntersectionAttempts = DiscIntersections = 0;
  119.     CylinderIntersectionAttempts = CylinderIntersections = 0;
  120.     ShadowAttempts=ShadowHits = 0;
  121.     ReflectedRays = 0;
  122.  
  123.     GotDisplayType = OpenDisplay(ReqDisplayType);    /* Open potential display */
  124.     displayopen=1;
  125.  
  126.     time(&starttrace);
  127.  
  128.     picturerendering=1;
  129.  
  130.     ScanWorld();                /* Make the actual ray-tracing */
  131.  
  132.     picturerendering=0;
  133.  
  134.     time(&endtrace);
  135.  
  136.     spenttime=(int)difftime(endtrace,starttrace);
  137.     spent_h=spenttime/(60*60);
  138.     spent_m=(spenttime%(60*60))/60;
  139.     spent_s=spenttime%60;
  140.  
  141.     fprintf(stderr,"\nDone!\n\n");
  142.     fprintf(stderr,"Shape              Tests        Hits\n");
  143.     fprintf(stderr,"-----------------------------------------------\n");
  144.     if(PlaneIntersectionAttempts>0)
  145.         fprintf(stderr,"Plane         %10ld  %10ld  (%3.2lf%%)\n",PlaneIntersectionAttempts,PlaneIntersections,((double)PlaneIntersections/(double)PlaneIntersectionAttempts)*100.0);
  146.     if(SphereIntersectionAttempts>0)
  147.         fprintf(stderr,"Sphere        %10ld  %10ld  (%3.2lf%%)\n",SphereIntersectionAttempts,SphereIntersections,((double)SphereIntersections/(double)SphereIntersectionAttempts)*100.0);
  148.     if(EllipsoidIntersectionAttempts>0)
  149.         fprintf(stderr,"Ellipsoid     %10ld  %10ld  (%3.2lf%%)\n",EllipsoidIntersectionAttempts,EllipsoidIntersections,((double)EllipsoidIntersections/(double)EllipsoidIntersectionAttempts)*100.0);
  150.     if(TriangleIntersectionAttempts>0)
  151.         fprintf(stderr,"Triangle      %10ld  %10ld  (%3.2lf%%)\n",TriangleIntersectionAttempts,TriangleIntersections,((double)TriangleIntersections/(double)TriangleIntersectionAttempts)*100.0);
  152.     if(BoxIntersectionAttempts>0)
  153.         fprintf(stderr,"Box           %10ld  %10ld  (%3.2lf%%)\n",BoxIntersectionAttempts,BoxIntersections,((double)BoxIntersections/(double)BoxIntersectionAttempts)*100.0);
  154.     if(DiscIntersectionAttempts>0)
  155.         fprintf(stderr,"Disc          %10ld  %10ld  (%3.2lf%%)\n",DiscIntersectionAttempts,DiscIntersections,((double)DiscIntersections/(double)DiscIntersectionAttempts)*100.0);
  156.     if(CylinderIntersectionAttempts>0)
  157.         fprintf(stderr,"Cylinder      %10ld  %10ld  (%3.2lf%%)\n",CylinderIntersectionAttempts,CylinderIntersections,((double)CylinderIntersections/(double)CylinderIntersectionAttempts)*100.0);
  158.     fprintf(stderr,"\nShadow rays:  tested: %ld   blocked: %ld  (%2.2lf%%)\n",ShadowAttempts,ShadowHits,100.0*(double)ShadowHits/(double)ShadowAttempts);
  159.     fprintf(stderr,"Reflected rays:  %ld\n",ReflectedRays);
  160.     fprintf(stderr,"\nTime: %dh %dmin %ds\n\n",spent_h,spent_m,spent_s);
  161.  
  162.  
  163. /*    if(AntiAliasingRec>=1L) {
  164.         free(aalinebuffer);
  165.     }
  166.  
  167.     FreeAllObjectMemory();
  168.  
  169.     fclose(outputfile);
  170.  */
  171.  
  172.     cleanup();
  173.  
  174.     exit(0);
  175. }
  176.  
  177.  
  178.  
  179. /**********************************************************************
  180.  *
  181.  *    cleanup() cleans up the system, closes down things etc...
  182.  *
  183.  **********************************************************************/
  184.  
  185. void cleanup(void) {
  186.     if(outfileopen==1) {
  187.         fclose(outputfile);
  188.         outfileopen=0;
  189.     }
  190.     if(aalinbufalloc==1) {
  191.         free(aalinebuffer);
  192.         aalinbufalloc=0;
  193.     }
  194.     if(displayopen==1) {
  195.         CloseDisplay();        /* Close display (if any was opened) */
  196.         displayopen=0;
  197.     }
  198.     if(objectalloc==1) {
  199.         FreeAllObjectMemory();    /* Free memory that was allocated for objects */
  200.         objectalloc=0;
  201.     }
  202. }
  203.  
  204.  
  205. /**********************************************************************
  206.  *
  207.  *    ScanWorld() is the main tracing routine
  208.  *
  209.  **********************************************************************/
  210.  
  211. void ScanWorld(void)
  212. {
  213.     long    column,line;
  214.     COLOR    ReturnColor;
  215.     LINE    ScanLine;
  216.     POINT    CameraLocation,ScreenLocation,OldScreenLocation;
  217.     VECTOR    vtemp,vxstep,vystep;
  218.     int    i,j;
  219.     unsigned char    RGBColor[3];
  220.     AAENTRY    *currentlinebufentry,*currentlinebufentry_tmp;
  221.  
  222.     CreatePoint(&CameraLocation,Camera.Location.x,Camera.Location.y,Camera.Location.z);
  223.     CopyPoint(&ScreenLocation,&CameraLocation);
  224.     ScaleVector(&vtemp,Camera.Aspect.z,&(Camera.Direction));
  225.     ScreenLocation.x+=vtemp.x; ScreenLocation.y+=vtemp.y; ScreenLocation.z+=vtemp.z;
  226.     ScaleVector(&vtemp,(Camera.Aspect.y)/(double)2,&(Camera.Up));
  227.     ScreenLocation.x+=vtemp.x; ScreenLocation.y+=vtemp.y; ScreenLocation.z+=vtemp.z;
  228.     ScaleVector(&vtemp,(Camera.Aspect.x)/(double)2,&(Camera.Right));
  229.     ScreenLocation.x-=vtemp.x; ScreenLocation.y-=vtemp.y; ScreenLocation.z-=vtemp.z;
  230.  
  231.     ScaleVector(&vxstep,(Camera.Aspect.x)/(double)PicWidth,&(Camera.Right));
  232.     ScaleVector(&vystep,-(Camera.Aspect.y)/(double)PicHeight,&(Camera.Up));
  233.  
  234.     if(AntiAliasingRec>=1L) {
  235.         currentlinebufentry=aalinebuffer;
  236.         for(column=0;column<PicWidth;column++) {    /* Clear antialiasing line-buffer */
  237.         for(i=0;i<aamaxlevel;i++) {
  238.             currentlinebufentry->Done=0;
  239.             currentlinebufentry++;
  240.         }
  241.         }
  242.     }
  243.  
  244.     for(line=1;line<=PicHeight;line++) {
  245.         if(AntiAliasingRec>=1L) {
  246.         for(i=0;i<aamaxlevel;i++) {
  247.             for(j=0;j<aamaxlevel;j++) {
  248.             aatable[i][j].Done=0;    /* Clear whole aatable */
  249.             }
  250.         }
  251.         currentlinebufentry=aalinebuffer;
  252.         }
  253.         CopyPoint(&OldScreenLocation,&ScreenLocation);
  254.         fprintf(stderr,"\rRendering line %ld of %ld (%3.1lf%%)",line,PicHeight,100.0*(double)line/(double)PicHeight);
  255.  
  256.         for(column=1;column<=PicWidth;column++) {
  257.         if(AntiAliasingRec<1L) {
  258.             MakeLine(&ScanLine,&CameraLocation,&ScreenLocation);
  259.             (void) TraceRay(&ReturnColor,&ScanLine,RecDepth);
  260.         }
  261.         else {
  262.             for(j=0;j<aamaxlevel;j++) {                /* Copy right column of last scan  to left column of new scan! */
  263.             if((aatable[0][j].Done=aatable[aamaxlevel-1][j].Done)!=0)
  264.                 CopyColor(&aatable[0][j].Color,&aatable[aamaxlevel-1][j].Color);
  265.             }
  266.             currentlinebufentry_tmp=currentlinebufentry;
  267.             for(i=0;i<aamaxlevel;i++) {                /* Copy top row from previous line */
  268.             if((aatable[i][0].Done=currentlinebufentry->Done)!=0)
  269.                 CopyColor(&aatable[i][0].Color,¤tlinebufentry->Color);
  270.             currentlinebufentry++;
  271.             }
  272.             for(i=1;i<aamaxlevel;i++) {
  273.                 for(j=1;j<aamaxlevel;j++) {
  274.                 aatable[i][j].Done=0;            /* Clear rest of aatable */
  275.             }
  276.             }
  277.             ScanOnePoint(&ReturnColor,&CameraLocation,&ScreenLocation,&vxstep,&vystep,0,aamaxlevel-1,0,aamaxlevel-1,AntiAliasingRec);
  278.             currentlinebufentry=currentlinebufentry_tmp;
  279.             for(i=0;i<aamaxlevel;i++) {                /* Save bottom row for next line */
  280.             if((currentlinebufentry->Done=aatable[i][aamaxlevel-1].Done)!=0)
  281.                 CopyColor(¤tlinebufentry->Color,&aatable[i][aamaxlevel-1].Color);
  282.             currentlinebufentry++;
  283.             }
  284.         }
  285.  
  286.         RGBColor[0] = (unsigned char)(255*ReturnColor.r);
  287.         RGBColor[1] = (unsigned char)(255*ReturnColor.g);
  288.         RGBColor[2] = (unsigned char)(255*ReturnColor.b);
  289.  
  290.         pixlearray[(column-1)*3+0] = RGBColor[0];
  291.         pixlearray[(column-1)*3+1] = RGBColor[1];
  292.         pixlearray[(column-1)*3+2] = RGBColor[2];
  293.  
  294.         if(GotDisplayType!=0L)
  295.             DisplayPlot((int)(column-1),(int)(line-1), RGBColor);
  296.  
  297.         ScreenLocation.x+=vxstep.x;
  298.         ScreenLocation.y+=vxstep.y;
  299.         ScreenLocation.z+=vxstep.z;
  300.         }
  301.         WriteTgaLine(outputfile,PicWidth);
  302.         CopyPoint(&ScreenLocation,&OldScreenLocation);
  303.         ScreenLocation.x+=vystep.x;
  304.         ScreenLocation.y+=vystep.y;
  305.         ScreenLocation.z+=vystep.z;
  306.     }
  307. }
  308.  
  309. void ScanOnePoint(COLOR *Color, POINT *CameraLocation, POINT *ScreenLocation, VECTOR *dx, VECTOR *dy, int ColumnFirst, int ColumnLast, int RowFirst, int RowLast, long AARec)
  310. {
  311.     LINE    ScanLine;
  312.     POINT    ScreenLocation2;
  313.     VECTOR    dx2,dy2;
  314.     COLOR    ReColor[4],MinColor,MaxColor;
  315.     double    ColorDiff;
  316.     int    i, DeltaColumn, DeltaRow;
  317.  
  318.     if(aatable[ColumnFirst][RowFirst].Done==0) {
  319.         MakeLine(&ScanLine,CameraLocation,ScreenLocation);
  320.         (void) TraceRay(&ReColor[0],&ScanLine,RecDepth);
  321.         aatable[ColumnFirst][RowFirst].Done=1;
  322.         CopyColor(&aatable[ColumnFirst][RowFirst].Color,&ReColor[0]);
  323.     }
  324.     else {
  325.         CopyColor(&ReColor[0],&aatable[ColumnFirst][RowFirst].Color);
  326.     }
  327.  
  328.     AddVector((VECTOR *)&ScreenLocation2,(VECTOR *)ScreenLocation,dx);
  329.     if(aatable[ColumnLast][RowFirst].Done==0) {
  330.         MakeLine(&ScanLine,CameraLocation,&ScreenLocation2);
  331.         (void) TraceRay(&ReColor[1],&ScanLine,RecDepth);
  332.         aatable[ColumnLast][RowFirst].Done=1;
  333.         CopyColor(&aatable[ColumnLast][RowFirst].Color,&ReColor[1]);
  334.     }
  335.     else {
  336.         CopyColor(&ReColor[1],&aatable[ColumnLast][RowFirst].Color);
  337.     }
  338.  
  339.     AddVector((VECTOR *)&ScreenLocation2,(VECTOR *)&ScreenLocation2,dy);
  340.     if(aatable[ColumnLast][RowLast].Done==0) {
  341.         MakeLine(&ScanLine,CameraLocation,&ScreenLocation2);
  342.         (void) TraceRay(&ReColor[2],&ScanLine,RecDepth);
  343.         aatable[ColumnLast][RowLast].Done=1;
  344.         CopyColor(&aatable[ColumnLast][RowLast].Color,&ReColor[2]);
  345.     }
  346.     else {
  347.         CopyColor(&ReColor[2],&aatable[ColumnLast][RowLast].Color);
  348.     }
  349.  
  350.     SubVector((VECTOR *)&ScreenLocation2,(VECTOR *)&ScreenLocation2,dx);
  351.     if(aatable[ColumnFirst][RowLast].Done==0) {
  352.         MakeLine(&ScanLine,CameraLocation,&ScreenLocation2);
  353.         (void) TraceRay(&ReColor[3],&ScanLine,RecDepth);
  354.         aatable[ColumnFirst][RowLast].Done=1;
  355.         CopyColor(&aatable[ColumnFirst][RowLast].Color,&ReColor[3]);
  356.     }
  357.     else {
  358.         CopyColor(&ReColor[3],&aatable[ColumnFirst][RowLast].Color);
  359.     }
  360.  
  361.     if(AARec>1L) {
  362.         CopyColor(&MinColor,&ReColor[0]);    /* Determine min/max values for r,g,b */
  363.         CopyColor(&MaxColor,&ReColor[0]);
  364.         for(i=1;i<4;i++) {
  365.         if(ReColor[i].r<MinColor.r) MinColor.r=ReColor[i].r;
  366.         else if(ReColor[i].r>MaxColor.r) MaxColor.r=ReColor[i].r;
  367.         if(ReColor[i].g<MinColor.g) MinColor.g=ReColor[i].g;
  368.         else if(ReColor[i].g>MaxColor.g) MaxColor.g=ReColor[i].g;
  369.         if(ReColor[i].b<MinColor.b) MinColor.b=ReColor[i].b;
  370.         else if(ReColor[i].b>MaxColor.b) MaxColor.b=ReColor[i].b;
  371.         }
  372.  
  373.         ColorDiff=MaxColor.r-MinColor.r+MaxColor.g-MinColor.g+MaxColor.b-MinColor.b;
  374.  
  375.         if(ColorDiff>AntiAliasingThreshold) {
  376.         ScaleVector(&dx2,0.5,dx);
  377.         ScaleVector(&dy2,0.5,dy);
  378.         DeltaColumn=(ColumnLast-ColumnFirst)>>1;
  379.         DeltaRow=(RowLast-RowFirst)>>1;
  380.  
  381.         ScanOnePoint(&ReColor[0],CameraLocation,ScreenLocation,&dx2,&dy2,ColumnFirst,ColumnFirst+DeltaColumn,RowFirst,RowFirst+DeltaRow,AARec-1);
  382.  
  383.         AddVector((VECTOR *)&ScreenLocation2,(VECTOR *)ScreenLocation,&dx2);
  384.         ScanOnePoint(&ReColor[1],CameraLocation,&ScreenLocation2,&dx2,&dy2,ColumnFirst+DeltaColumn,ColumnLast,RowFirst,RowFirst+DeltaRow,AARec-1);
  385.  
  386.         AddVector((VECTOR *)&ScreenLocation2,(VECTOR *)&ScreenLocation2,&dy2);
  387.         ScanOnePoint(&ReColor[2],CameraLocation,&ScreenLocation2,&dx2,&dy2,ColumnFirst+DeltaColumn,ColumnLast,RowFirst+DeltaRow,RowLast,AARec-1);
  388.  
  389.         SubVector((VECTOR *)&ScreenLocation2,(VECTOR *)&ScreenLocation2,&dx2);
  390.         ScanOnePoint(&ReColor[3],CameraLocation,&ScreenLocation2,&dx2,&dy2,ColumnFirst,ColumnFirst+DeltaColumn,RowFirst+DeltaRow,RowLast,AARec-1);
  391.         }
  392.     }
  393.  
  394.     CopyColor(Color,&ReColor[0]);
  395.     for(i=1;i<4;i++) {
  396.         Color->r+=ReColor[i].r;
  397.         Color->g+=ReColor[i].g;
  398.         Color->b+=ReColor[i].b;
  399.     }
  400.     Color->r*=0.25; Color->g*=0.25; Color->b*=0.25;
  401. }
  402.  
  403.  
  404. /**********************************************************************
  405.  *
  406.  *    TraceRay() will trace a given ray and return a resulting color
  407.  *
  408.  **********************************************************************/
  409.  
  410. long TraceRay(COLOR *Color, LINE *RayLine, long RecurseLevel)
  411. {
  412.     double    t,tnew,angle,dintense,pintense;
  413.     LINE    LightLine,ReflectLine;
  414.     POINT    IPoint;
  415.     VECTOR    surfnormal,reflectvect;
  416.     COLOR    surfcolor,ReflectedColor;
  417.     long    i,ObjNum=-1;
  418.  
  419.  
  420.     /* Find closest hit */
  421.     if(RecurseLevel>0) {
  422.     t=-1;
  423.     for(i=0;i<NumObjects;i++) {
  424.         tnew=Intersect_Object(RayLine, ObjectArray[i]);
  425.         if((tnew>EPSILON)&&((tnew<t)||(t<=EPSILON))) {
  426.         ObjNum=i;
  427.         t=tnew;
  428.         }
  429.     }
  430.  
  431.     /* Calculate color in intersected point */
  432.     if(ObjNum>=0) {
  433.         IPoint.x=RayLine->Origin.x+t*RayLine->Direction.x;
  434.         IPoint.y=RayLine->Origin.y+t*RayLine->Direction.y;
  435.         IPoint.z=RayLine->Origin.z+t*RayLine->Direction.z;
  436.         if(fabs(IPoint.x+IPoint.y+IPoint.z)>maxsumcoord) {
  437.         ObjNum=-1;
  438.         Color->r=BackgroundColor.r;
  439.         Color->g=BackgroundColor.g;
  440.         Color->b=BackgroundColor.b;
  441.         }
  442.         else {
  443.         GetSurfaceColor(&surfcolor, &ObjectArray[ObjNum]->Texture, &IPoint);
  444.         GetSurfaceNormal(&surfnormal, &IPoint, ObjectArray[ObjNum]);
  445.         angle=VectorsAngle(&surfnormal,&(RayLine->Direction));
  446.         if(angle<PID2) NegVector(&surfnormal,&surfnormal);    /* So that the surface-normal always points towards us */
  447.  
  448.         ReflectVector(&reflectvect,&(RayLine->Direction),&surfnormal);
  449.  
  450.         Color->r=Color->g=Color->b=0.0;
  451.  
  452.         for(i=0;i<NumLights;i++) {
  453.             dintense=0.0;
  454.             pintense=0.0;
  455.             MakeLine(&LightLine,&IPoint,&(LightArray[i]->Location));
  456.             if(TestShadowRay(&LightLine,ObjNum)<0) {
  457.             angle=VectorsAngle(&surfnormal,&(LightLine.Direction));
  458.             if(angle<PID2) {
  459.                 dintense=ObjectArray[ObjNum]->Texture.Diffuse*cos(angle);
  460.  
  461.                 angle=VectorsAngle(&reflectvect,&(LightLine.Direction));
  462.                 if(angle<PID2) {
  463.                 pintense=ObjectArray[ObjNum]->Texture.Phong*pow(cos(angle),ObjectArray[ObjNum]->Texture.PhongSize);
  464.                 }
  465.             }
  466.             }
  467.             dintense = (dintense > 1.0 ? 1.0 : dintense);
  468.             pintense = (pintense > 1.0 ? 1.0 : pintense);
  469.  
  470.             Color->r+=((dintense*surfcolor.r+pintense)*LightArray[i]->Color.r);
  471.             Color->g+=((dintense*surfcolor.g+pintense)*LightArray[i]->Color.g);
  472.             Color->b+=((dintense*surfcolor.b+pintense)*LightArray[i]->Color.b);
  473.         }
  474.         Color->r+=surfcolor.r*ObjectArray[ObjNum]->Texture.Ambient;
  475.         Color->g+=surfcolor.g*ObjectArray[ObjNum]->Texture.Ambient;
  476.         Color->b+=surfcolor.b*ObjectArray[ObjNum]->Texture.Ambient;
  477.  
  478.         if((ObjectArray[ObjNum]->Texture.Reflect.r+ObjectArray[ObjNum]->Texture.Reflect.g+ObjectArray[ObjNum]->Texture.Reflect.b)>EPSILON) {
  479.             ReflectedRays++;
  480.             CopyVector(&(ReflectLine.Direction),&reflectvect);
  481.             CopyPoint(&(ReflectLine.Origin),&IPoint);
  482.             TraceRay(&ReflectedColor, &ReflectLine, RecurseLevel-1L);
  483.             Color->r+=(ObjectArray[ObjNum]->Texture.Reflect.r*ReflectedColor.r);
  484.             Color->g+=(ObjectArray[ObjNum]->Texture.Reflect.g*ReflectedColor.g);
  485.             Color->b+=(ObjectArray[ObjNum]->Texture.Reflect.b*ReflectedColor.b);
  486.         }
  487.  
  488.         Color->r = (Color->r > 1.0 ? 1.0 : Color->r);
  489.         Color->g = (Color->g > 1.0 ? 1.0 : Color->g);
  490.         Color->b = (Color->b > 1.0 ? 1.0 : Color->b);
  491.         }
  492.     }
  493.     else {
  494.         Color->r=BackgroundColor.r;
  495.         Color->g=BackgroundColor.g;
  496.         Color->b=BackgroundColor.b;
  497.     }
  498.     }
  499.     else {
  500.     Color->r=0.0;    /* Return no color (= color black) if recursion- */
  501.     Color->g=0.0;   /* level <= 0                                    */
  502.     Color->b=0.0;
  503.     }
  504.  
  505.     return(ObjNum);
  506. }
  507.  
  508.  
  509.  
  510. /**********************************************************************
  511.  *
  512.  *    TestShadowRay() will trace a given ray and look for object-hits
  513.  *
  514.  **********************************************************************/
  515.  
  516.  
  517. long TestShadowRay(LINE *RayLine, long CurrentObject)
  518. {
  519.     long    i,hit=-1;
  520.     double    t,told=-1;
  521.  
  522.     ShadowAttempts++;
  523.     for(i=0;i<NumObjects;i++) {
  524.         if(i!=CurrentObject) {
  525.         t=Intersect_Object(RayLine, ObjectArray[i]);
  526.         if((t>EPSILON)&&((t<told)||(told<=EPSILON))) {
  527.             hit=i;
  528.             told=t;
  529.         }
  530.         }
  531.     }
  532.     t=told;
  533.  
  534.     if(t>1.0) hit=-1;        /* Object was beyond light */
  535.     if(hit>=0) ShadowHits++;
  536.  
  537.     return(hit);
  538. }
  539.